#include "mainwindow.h"

#include <QtCharts>
#include <cmath>
#include <ctime>
#include <random>

#include "pensetdialog.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->createChart();
    this->prepareData();

    // 刷新
    connect(ui->actDraw, &QAction::triggered, this, &MainWindow::prepareData);

    // 设置标题文字
    connect(ui->btnTitleSetText, &QPushButton::clicked, this, [this]() {
        this->chart->setTitle(ui->editTitle->text());
    });

    // 设置标题文字颜色
    connect(ui->btnTitleColor, &QPushButton::clicked, this, [this]() {
        QColor color = this->chart->titleBrush().color();
        color = QColorDialog::getColor(color);
        if (color.isValid())
        {
            this->chart->setTitleBrush(QBrush(color));
        }
    });

    // 设置字体
    connect(ui->btnTitleFont, &QPushButton::clicked, this, [this]() {
        QFont font = this->chart->titleFont();
        bool result = false;
        font = QFontDialog::getFont(&result, font);
        if (result)
        {
            this->chart->setTitleFont(font);
        }
    });

    // 是否显示图例
    connect(ui->groupBox_Legend, &QGroupBox::clicked, this, [this](bool checked) {
        this->chart->legend()->setVisible(checked);
    });
    // 图例位置
    connect(ui->radioButton_up, &QRadioButton::clicked, this, [this]() {
        if (ui->radioButton_up->isChecked())
        {
            this->chart->legend()->setAlignment(Qt::AlignTop);
        }
    });
    connect(ui->radioButton_down, &QRadioButton::clicked, this, [this]() {
        if (ui->radioButton_down->isChecked())
        {
            this->chart->legend()->setAlignment(Qt::AlignBottom);
        }
    });
    connect(ui->radioButton_left, &QRadioButton::clicked, this, [this]() {
        if (ui->radioButton_left->isChecked())
        {
            this->chart->legend()->setAlignment(Qt::AlignLeft);
        }
    });
    connect(ui->radioButton_right, &QRadioButton::clicked, this, [this]() {
        if (ui->radioButton_right->isChecked())
        {
            this->chart->legend()->setAlignment(Qt::AlignRight);
        }
    });
    // 图例文字颜色
    connect(ui->btnLegendlabelColor, &QPushButton::clicked, this, [this]() {
        QColor color = this->chart->legend()->labelColor();
        color = QColorDialog::getColor(color);
        if (color.isValid())
        {
            this->chart->legend()->setLabelColor(color);
        }
    });
    // 图例文字字体
    connect(ui->btnLegendFont, &QPushButton::clicked, this, [this]() {
        QFont font = this->chart->titleFont();
        bool result = false;
        font = QFontDialog::getFont(&result, font);
        if (result)
        {
            this->chart->legend()->setFont(font);
        }
    });

    // 设置边距
    connect(ui->btnSetMargin, &QPushButton::clicked, this, [this]() {
        QMargins margins;
        margins.setTop(ui->spinMarginTop->value());
        margins.setBottom(ui->spinMarginBottom->value());
        margins.setLeft(ui->spinMarginLeft->value());
        margins.setRight(ui->spinMarginRight->value());
        this->chart->setMargins(margins);
    });

    // 动画
    connect(ui->comboAnimation, &QComboBox::currentIndexChanged, this, [this](int index) {
        this->chart->setAnimationOptions(QChart::AnimationOption(index));
    });

    // 主题
    connect(ui->comboTheme, &QComboBox::currentIndexChanged, this, [this](int index) {
        this->chart->setTheme(QChart::ChartTheme(index));
    });

    // 点击后更新选项
    connect(ui->radioSeries0, &QRadioButton::clicked, this, [this]() {
        if (!ui->radioSeries0->isChecked())
        {
            return;
        }
        this->currentSeries = (QLineSeries*)(this->chart->series().at(0));
        this->updateWithCurrentSeries();
    });
    connect(ui->radioSeries1, &QRadioButton::clicked, this, [this]() {
        if (!ui->radioSeries1->isChecked())
        {
            return;
        }
        this->currentSeries = (QLineSeries*)(this->chart->series().at(1));

        this->updateWithCurrentSeries();
    });

    // 序列曲线
    connect(ui->groupBox_Series, &QGroupBox::clicked, this, [this](bool clicked) {
        this->currentSeries->setVisible(clicked);
    });

    // 设置序列名称
    connect(ui->btnSeriesName, &QPushButton::clicked, this, [this]() {
        this->currentSeries->setName(ui->editSeriesName->text());
        if (ui->radioSeries0->isChecked())
        {
            ui->radioSeries0->setText(ui->editSeriesName->text());
        }
        else if (ui->radioSeries1->isChecked())
        {
            ui->radioSeries1->setText(ui->editSeriesName->text());
        }
    });
    // 设置序列颜色
    connect(ui->btnSeriesColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentSeries->color());
        if (color.isValid())
        {
            this->currentSeries->setColor(color);
        }
    });
    // 设置序列画笔
    connect(ui->btnSeriesPen, &QPushButton::clicked, this, [this]() {
        bool result = false;

        QPen pen = PenSetDialog::getPen(this->currentSeries->pen(), &result);
        if (result)
        {
            this->currentSeries->setPen(pen);
        }
    });

    // 设置序列透明度
    connect(ui->sliderOpacity, &QSlider::sliderMoved, this, [this](int position) {
        this->currentSeries->setOpacity(position / 10.0);
    });

    // 设置数据点是否可见
    connect(ui->groupBox_Points, &QGroupBox::clicked, this, [this](bool checked) {
        this->currentSeries->setPointsVisible(checked);
    });
    // 设置数据点大小
    connect(ui->doubleSpinBox, &QDoubleSpinBox::valueChanged, this, [this](double size) {
        this->currentSeries->setMarkerSize(size);
    });
    // 设置数据点颜色
    connect(ui->btnPointColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor();
        if (color.isValid())
        {
            this->currentSeries->setColor(color);
        }
    });
    // 设置数据点标签是否可见
    connect(ui->groupBox_PointLabel, &QGroupBox::clicked, this, [this](bool checked) {
        this->currentSeries->setPointLabelsVisible(checked);
    });
    // 设置数据点标签颜色
    connect(ui->btnSeriesLabColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentSeries->pointLabelsColor());
        if (color.isValid())
        {
            this->currentSeries->setPointLabelsColor(color);
        }
    });
    // 设置数据点标签字体
    connect(ui->btnSeriesLabFont, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QFont font = QFontDialog::getFont(&result, this->currentSeries->pointLabelsFont());
        if (result)
        {
            this->currentSeries->setPointLabelsFont(font);
        }
    });
    // 设置标签格式
    connect(ui->radioSeriesLabFormat0, &QRadioButton::clicked, this, [this]() {
        this->currentSeries->setPointLabelsFormat("@yPoint"); // 只显示纵坐标
    });
    connect(ui->radioSeriesLabFormat1, &QRadioButton::clicked, this, [this]() {
        this->currentSeries->setPointLabelsFormat("@xPoint,@yPoint"); // 显示横纵坐标
    });

    /* 坐标轴设置 */
    // X轴
    connect(ui->radioAxisX, &QRadioButton::clicked, this, [this]() {
        if (!(ui->radioAxisX->isChecked()))
        {
            return;
        }
        this->currentAxis = static_cast<QValueAxis*>(this->chart->axes(Qt::Horizontal).at(0));
        this->updateWithCurrentAxis();
    });
    // Y轴
    connect(ui->radioAxisY, &QRadioButton::clicked, this, [this]() {
        if (!(ui->radioAxisY->isChecked()))
        {
            return;
        }
        this->currentAxis = static_cast<QValueAxis*>(this->chart->axes(Qt::Vertical).at(0));
        this->updateWithCurrentAxis();
    });

    // 刻度方向
    connect(ui->chkBoxAxisReverse, &QCheckBox::clicked, this, [this](bool checked) {
        this->currentAxis->setReverse(checked); // 刻度方向是否反转
    });
    // 范围
    connect(ui->btnSetAxisRange, &QPushButton::clicked, this, [this]() {
        this->currentAxis->setRange(ui->spinAxisMin->value(), ui->spinAxisMax->value());
    });
    // 标题是否可见
    connect(ui->groupBox_AxisTitle, &QGroupBox::clicked, this, [this](bool checked) {
        this->currentAxis->setTitleVisible(checked);
    });
    // 标题内容
    connect(ui->btnAxisSetTitle, &QPushButton::clicked, this, [this]() {
        this->currentAxis->setTitleText(ui->editAxisTitle->text());
    });
    // 标题颜色
    connect(ui->btnAxisTitleColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentAxis->titleBrush().color());
        if (color.isValid())
        {
            this->currentAxis->setTitleBrush(QBrush(color));
        }
    });
    // 标题字体
    connect(ui->btnAxisTitleFont, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QFont font = QFontDialog::getFont(&result, this->currentAxis->titleFont());
        if (result)
        {
            this->currentAxis->setTitleFont(font);
        }
    });
    // 标签格式
    connect(ui->btnAxisLabelFormat, &QPushButton::clicked, this, [this]() {
        this->currentAxis->setLabelFormat(ui->editAxisLabelFormat->text());
    });
    // 标签颜色
    connect(ui->btnAxisLabelColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentAxis->labelsColor());
        if (color.isValid())
        {
            this->currentAxis->setLabelsColor(color);
        }
    });
    // 标签字体
    connect(ui->btnAxisLabelFont, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QFont font = QFontDialog::getFont(&result, this->currentAxis->labelsFont());
        if (result)
        {
            this->currentAxis->setLabelsFont(font);
        }
    });
    /*轴线和主刻度*/
    // 动态刻度
    connect(ui->radioTick_Dynamic, &QRadioButton::clicked, this, [this]() {
        this->currentAxis->setTickType(QValueAxis::TicksDynamic);
    });
    // 固定刻度
    connect(ui->radioTick_Fixed, &QRadioButton::toggled, this, [this](bool checked) {
        ui->spinTick_Count->setEnabled(checked);
        ui->spinTick_Anchor->setEnabled(!checked);
        ui->spinTick_Intv->setEnabled(!checked);
    });
    // 建议数值轴（Value Axis）上主要刻度线（major ticks）及其标签的大致数量。
    connect(ui->spinTick_Count, &QSpinBox::valueChanged, this, [this](int arg1) {
        this->currentAxis->setTickCount(arg1);
    });
    // 主刻度线起始位置
    connect(ui->spinTick_Anchor, &QDoubleSpinBox::valueChanged, this, [this](double value) {
        this->currentAxis->setTickAnchor(value);
    });
    // 间隔
    connect(ui->spinTick_Intv, &QDoubleSpinBox::valueChanged, this, [this](double value) {
        this->currentAxis->setTickInterval(value);
    });
    // 轴线线条
    connect(ui->btnAxisLinePen, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QPen pen = PenSetDialog::getPen(this->currentAxis->linePen(), &result);
        if (result)
        {
            this->currentAxis->setLinePen(pen);
        }
    });
    // 轴线颜色
    connect(ui->btnAxisLinePenColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentAxis->linePenColor());
        if (color.isValid())
        {
            this->currentAxis->setLinePenColor(color);
        }
    });
    /*主网格线*/
    // 是否可见
    connect(ui->groupBox_GridLine, &QGroupBox::clicked, this, [this](bool checked) {
        this->currentAxis->setGridLineVisible(checked);
    });
    // 线条
    connect(ui->btnGridLinePen, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QPen pen = PenSetDialog::getPen(this->currentAxis->gridLinePen(), &result);
        if (result)
        {
            this->currentAxis->setGridLinePen(pen);
        }
    });
    // 颜色
    connect(ui->btnGridLineColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentAxis->gridLineColor());
        if (color.isValid())
        {
            this->currentAxis->setGridLineColor(color);
        }
    });
    /*次网格线*/
    // 线条
    connect(ui->btnMinorPen, &QPushButton::clicked, this, [this]() {
        bool result = false;
        QPen pen = PenSetDialog::getPen(this->currentAxis->minorGridLinePen(), &result);
        if (result)
        {
            this->currentAxis->setMinorGridLinePen(pen);
        }
    });
    // 颜色
    connect(ui->btnMinorColor, &QPushButton::clicked, this, [this]() {
        QColor color = QColorDialog::getColor(this->currentAxis->minorGridLineColor());
        if (color.isValid())
        {
            this->currentAxis->setMinorGridLineColor(color);
        }
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::updateWithCurrentSeries()
{
    ui->editSeriesName->setText(this->currentSeries->name());
    ui->groupBox_Series->setChecked(this->currentSeries->isVisible());
    ui->groupBox_Points->setChecked(this->currentSeries->pointsVisible());
    ui->chkkBoxUseOpenGL->setChecked(this->currentSeries->useOpenGL());             // 使用openGL，硬件加速
    ui->sliderOpacity->setValue(this->currentSeries->opacity() * 10);               // 不透明度
    ui->groupBox_PointLabel->setChecked(this->currentSeries->pointLabelsVisible()); // 控制是否在图表的数据点旁边显示标签
}

void MainWindow::updateWithCurrentAxis()
{
    ui->groupBox_Axis->setChecked(this->currentAxis->isVisible());
    ui->chkBoxAxisReverse->setChecked(this->currentAxis->isReverse());
    ui->spinAxisMax->setValue(this->currentAxis->max());
    ui->spinAxisMin->setValue(this->currentAxis->min());
    ui->groupBox_AxisTitle->setChecked(this->currentAxis->isTitleVisible());
    ui->editAxisTitle->setText(this->currentAxis->titleText());
    ui->editAxisLabelFormat->setText(this->currentAxis->labelFormat());
    ui->groupBox_Ticks->setChecked(this->currentAxis->isLineVisible());
    if (this->currentAxis->tickType() == QValueAxis::TicksFixed)
    {
        ui->radioTick_Fixed->setChecked(true);
    }
    else
    {
        ui->radioTick_Fixed->setChecked(false);
    }
    ui->spinTick_Anchor->setValue(this->currentAxis->tickAnchor()); // 动态刻度起点
    ui->spinTick_Intv->setValue(currentAxis->tickInterval());       // 动态刻度间隔
    ui->spinTick_Count->setValue(currentAxis->tickCount());         // 主刻度个数

    /* 网格线*/
    ui->groupBox_GridLine->setChecked(this->currentAxis->isGridLineVisible());
    ui->groupBox_MinorGrid->setCheckable(this->currentAxis->isMinorGridLineVisible());
    ui->spinMinorTickCount->setValue(this->currentAxis->minorTickCount()); // 次刻度个数
}

void MainWindow::createChart()
{
    this->chart = new QChart();
    chart->setTitle("简单函数显示");

    ui->chartView->setChart(this->chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing); // 打开抗锯齿

    QLineSeries* series0 = new QLineSeries();
    QLineSeries* series1 = new QLineSeries();

    series0->setName("Sin曲线");
    series1->setName("Cos曲线");

    this->currentSeries = series0;

    QPen pen0;
    pen0.setStyle(Qt::DotLine);
    pen0.setColor(Qt::red);
    pen0.setWidth(2);

    series0->setPen(pen0);

    QPen pen1;
    pen1.setStyle(Qt::DotLine);
    pen1.setColor(Qt::blue);
    pen1.setWidth(2);

    series0->setPen(pen1);

    chart->addSeries(series0);
    chart->addSeries(series1);

    QValueAxis* axisX = new QValueAxis();
    this->currentAxis = axisX;
    axisX->setRange(0, 10);        // 范围
    axisX->setLabelFormat("%.1f"); // 格式
    axisX->setTickCount(10);       // 设置X轴上主刻度线（Major Ticks）的数量
    axisX->setTitleText("time(secs)");
    QValueAxis* axisY = new QValueAxis();
    this->currentAxis = axisY;
    axisY->setRange(-2, 2);        // 设置Y轴的显示范围
    axisY->setLabelFormat("%.1f"); // 格式
    axisY->setTickCount(5);        // 设置Y轴上主刻度线（Major Ticks）的数量
    axisY->setMinorTickCount(2);   // 设置主刻度线之间的次刻度线（Minor Ticks）的数量。
    axisY->setTitleText("value");

    this->chart->addAxis(axisX, Qt::AlignBottom); // 加入X轴
    this->chart->addAxis(axisY, Qt::AlignLeft);   // 加入Y轴

    series0->attachAxis(axisX);
    series0->attachAxis(axisY);
    series1->attachAxis(axisX);
    series1->attachAxis(axisY);
}

void MainWindow::prepareData()
{
    QLineSeries* series0 = static_cast<QLineSeries*>(this->chart->series().at(0)); // 获取列表中指定索引位置的元素的常量引用
    series0->clear();
    double x0 = 0, intv0 = 0.1;
    for (int i = 0; i < 100; i++)
    {
        int rd = QRandomGenerator::global()->bounded(-5, 6); // 随机数
        series0->append(x0, std::sin(x0) + rd / 50.0);
        x0 += intv0;
    }

    QLineSeries* series1 = static_cast<QLineSeries*>(this->chart->series().at(1)); // 获取列表中指定索引位置的元素的常量引用
    series1->clear();
    double x1 = 0, intv1 = 0.1;
    for (int i = 0; i < 100; i++)
    {
        int rd = QRandomGenerator::global()->bounded(-5, 6); // 随机数
        series1->append(x1, std::cos(x1) + rd / 50.0);
        x1 += intv1;
    }
}

void MainWindow::updateFromChart()
{
    QChart* curChart = ui->chartView->chart();
    ui->editTitle->setText(curChart->title());

    // 外边距
    QMargins mg = curChart->margins();
    ui->spinMarginLeft->setValue(mg.left());
}
